﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Threading;
using TheJoyOfCode.SLUploader.UploadService;
using System.IO;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Threading;

namespace TheJoyOfCode.SLUploader
{
    public class Uploader : TheJoyOfCode.SLUploader.IUploader
    {
        private readonly Uri _serviceUri;
        private readonly IFileUploadView _fileUploadView;

        public Uploader(IFileUploadView fileUploadView, Uri serviceUri)
        {
            _serviceUri = serviceUri;
            _fileUploadView = fileUploadView;
        }

        public void UploadFilesAsync(Queue<FileInfo> files)
        {
            ThreadPool.QueueUserWorkItem(ignored => UploadFiles(files));
        }

        private void UploadFiles(Queue<FileInfo> files)
        {
            UploadFileService service = new UploadFileService(_serviceUri, _fileUploadView.Dispatcher);
            int uploadedFiles = 0;
            int totalFilesToUpload = files.Count;


            while (files.Count > 0)
            {
                FileInfo fileInfo = files.Dequeue();
                OnFileUploadStarted(fileInfo);
                try
                {
                    service.UploadFile(fileInfo, false);
                    uploadedFiles++;
                    OnFileUploadComplete(fileInfo, uploadedFiles, totalFilesToUpload);
                }
                catch (FileExistsException)
                {
                    if (_fileUploadView.ConfirmOverwrite(fileInfo))
                    {
                        service.UploadFile(fileInfo, true);
                        uploadedFiles++;
                        OnFileUploadComplete(fileInfo, uploadedFiles, totalFilesToUpload);
                    }
                }
                catch (Exception exc)
                {
                    Debug.Assert(false, exc.ToString());
                }
            }

            OnUploadsComplete(uploadedFiles, totalFilesToUpload);
        }


        protected virtual void OnFileUploadStarted(FileInfo fileInfo)
        {
            if (FileUploadStarted != null)
            {
                FileUploadStarted(this, new FileUploadStartedEventArgs()
                {
                    FileInfo = fileInfo
                });
            }
        }

         protected virtual void OnFileUploadComplete(FileInfo fileInfo, int uploadedFiles, int totalFilesToUpload)
        {
            if (FileUploadComplete != null)
            {
                FileUploadComplete(this, new FileUploadedCompletedEventArgs()
                {
                    FileInfo = fileInfo,
                    TotalFilesToUpload = totalFilesToUpload,
                    UploadedFiles = uploadedFiles
                });
            }
        }

        protected virtual void OnUploadsComplete(int uploadedFiles, int totalFilesToUpload)
        {
            if (UploadsComplete != null)
            {
                UploadsComplete(this, new UploadsCompleteEventArgs()
                {
                    UploadedFiles = uploadedFiles,
                    TotalFilesToUpload = totalFilesToUpload
                });
            }
        }

        public event EventHandler<FileUploadStartedEventArgs> FileUploadStarted;
        public event EventHandler<FileUploadedCompletedEventArgs> FileUploadComplete;
        public event EventHandler<UploadsCompleteEventArgs> UploadsComplete;
    }

    public class UploadsCompleteEventArgs : EventArgs
    {
        public double TotalFilesToUpload { get; set; }
        public int UploadedFiles { get; set; }
    }

    public class FileUploadStartedEventArgs : EventArgs
    {
        public FileInfo FileInfo { get; set; }
    }

    public class FileUploadedCompletedEventArgs : FileUploadStartedEventArgs
    {
        public double TotalFilesToUpload { get; set; }
        public int UploadedFiles { get; set; }
    }
}
